#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QSerialPort>
#include <QSerialPortInfo>
#include <QHostAddress>
#include <QTimer>
#include <QMap>
#include <QLabel>
#include <QMetaType>
#include <QMetaObject>
#include <QApplication>
#include <QHash>
#include <QSet>

#include "core/DriverController.h"
#include "control/DataControl.h"


#define MIME_TYPE "application/x-comport"
#define MWIND qApp->property("stApp").value<MainWindow*>()
#define ADD_LOG(MSG) do { \
    MainWindow* __mw = MWIND; \
    if (__mw) { \
        QMetaObject::invokeMethod(__mw, "addLogMessage", Qt::QueuedConnection, Q_ARG(QString, QString(MSG))); \
    } else { \
        qWarning() << "MWIND is nullptr!"; \
    } \
} while(0)

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class DriverManager;
class DataControl;

/**
 * @brief Main window class
 * Provides user interface, manages serial port splitter
 */
class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    /**
     * @brief Constructor
     * @param parent Parent window
     */
    MainWindow(QWidget *parent = nullptr);
    
    /**
     * @brief Destructor
     */
    ~MainWindow();

signals:
    void newLogMessage(const QString &message);

public slots:
    void addSerialPortToEndPoints(const QString &portName, bool isVirtual = false);

private slots:
    /**
     * @brief Refresh serial port list
     */
    void refreshSerialPorts();
    
    /**
     * @brief Start/stop button click handler
     */
    void onStartStopButtonClicked();
    
    /**
     * @brief Add serial endpoint button click handler
     */
    void onAddSerialEndpointClicked();
    
    /**
     * @brief Add UDP endpoint button click handler
     */
    void onAddUdpEndpointClicked();

    /**
     * @brief Remove endpoint button click handler
     */
    void onRemoveEndpointClicked();
        
    /**
     * @brief Send button click handler
     */
    void onSendButtonClicked();
    
    /**
     * @brief Physical port data received handler
     * @param data Received data
     */
    void onInputPortDataReceived(const QByteArray &data);
    
    /**
     * @brief Endpoint data received handler
     * @param name Endpoint name
     * @param data Data
     */
    void onEndpointPortDataReceived(const QString &name, const QByteArray &data);
        
    /**
     * @brief Error handler
     * @param message Error message
     */
    void onError(const QString &message);

    /**
     * @brief Periodic flush timer handler for small buffered data
     */
    void onDataFlushTimerTick();

    /**
     * @brief Stats updated handler (display overall throughput and errors)
     */
    void onStatsUpdated(const TransferStats &total, const EndpointStatsMap &perEndpoint);

private:
    /**
     * @brief Initialize UI
     */
    void initializeUi();
    
    /**
     * @brief Initialize connections
     */
    void initializeConnections();
    
    /**
     * @brief Initialize Deriver Config
     */
    void initializeDeriver();

    /**
     * @brief Update UI state
     */
    void updateUiState();
   
    /**
     * @brief Update target endpoint combo box
     */
    void updateTargetComboBox();

    /**
     * @brief Add log message
     * @param message Log message
     */
    Q_INVOKABLE void addLogMessage(const QString &message);

    /**
     * @brief Add data log
     * @param source Data source
     * @param data Data
     * @param direction Direction (send/receive)
     */
    void addDataLog(const QString &source, const QByteArray &data, const QString &direction, bool isImmediate = false);
    
private:
    Ui::MainWindow *ui;
    DriverController *m_driverController;
    DataControl *m_dataControl;
    QTimer *m_refreshTimer;
    QLabel *m_statusLabel;
    QLabel *m_statsLabel;
    QStringList m_curSerialList;
    bool m_isRunning;
    
    int m_dataFlushThresholdBytes; // 缓冲区阈值（字节数），达到后一次性输出
    QTimer *m_dataFlushTimer;      // 定时器：定时冲刷未满的数据
    int m_dataFlushIntervalMs;     // 定时器间隔（毫秒）

    // 定时输出所需的缓冲、状态
    QHash<QString, QByteArray> m_asciiPendingBySource; // 每源的待输出ASCII缓冲
    QSet<QString> m_printedHeaders;                    // 已打印过的头部标识
    QString m_lastLogHeader;                           // 最后一次打印的头部内容
};

Q_DECLARE_METATYPE(MainWindow*)

#endif // MAINWINDOW_H
